﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Drawing.Imaging;

namespace Server
{ 
    public partial class ScreenChooser : Form
    {
        [DllImport("MyMouseHook.dll")]
        public static extern void Hook(IntPtr hWnd);
        [DllImport("MyMouseHook.dll")]
        public static extern void unHook();
        private ToolTip wSugg;
        private ToolTip sSugg;

        private bool windowMode;

        /// <summary>
        /// Specifica se l'utente ha scelto di trasmettere una finestra specifica.
        /// Per ottenere l'handle della finestra selezionatta, utilizzare la proprietà ScreenChooser.CapturedWindow
        /// </summary>
        public bool WindowMode
        {
            get { return windowMode; }
        }

        /// <summary>
        /// Specifica se l'utente ha scelto di trasmettere una porzione di schermo.
        /// Per ottenere il rettangolo selezionato utilizzare la proprietà ScreenChooser.CapturedRectangle
        /// </summary>
        public bool ScreenMode
        {
            get { return !windowMode; }
        }

        private bool captured;

        private IntPtr capturedWindow;

        public IntPtr CapturedWindow
        {
            get{ return capturedWindow; }
        }

        private Point screenStartPoint;
        private Size screenSize;

        public Rectangle CapturedRectangle
        {
            get { return new Rectangle(screenStartPoint, screenSize); }
        }

        public ScreenChooser()
        {
            InitializeComponent();
            captured = false;
            InitSuggestion();
        }

        public void InitSuggestion() 
        {
            wSugg = new ToolTip();
            sSugg = new ToolTip();
            wSugg.AutoPopDelay = 4000;
            wSugg.InitialDelay = 5;
            wSugg.SetToolTip(WindowButton, "Press this button, then click" + Environment.NewLine + "on the window you want to capture");
            sSugg.AutoPopDelay = 4000;
            sSugg.InitialDelay = 5;
            sSugg.SetToolTip(ScreenButton, "Press this button to choose the portion" + Environment.NewLine + "of the screen you want to capture");
        }

        protected override void WndProc(ref Message m)
        {
            const int MOUSE_DOWN = 0x0401;
            if (m.Msg == MOUSE_DOWN)
            {
                Point pos = Cursor.Position;
                if (windowMode)
                {
                    unHook();
                    
                    capturedWindow = CaptureClass.WindowFromPoint(pos);

                    bool minimized = false;
                    Bitmap capturedImage = CaptureClass.CaptureWindow(capturedWindow, out minimized);

                    bool translate = false;

                    float xTranslate = 0.0F;
                    float yTranslate = 0.0F;

                    Size bitmapSize = capturedImage.Size;

                    if (bitmapSize.Width < pictureBox1.MinimumSize.Width)
                    {
                        xTranslate = (pictureBox1.MinimumSize.Width - bitmapSize.Width) / 2;
                        bitmapSize.Width = pictureBox1.MinimumSize.Width;
                        translate = true;
                    }
                    if (bitmapSize.Height < pictureBox1.MinimumSize.Height)
                    {
                        yTranslate = (pictureBox1.MinimumSize.Height - bitmapSize.Height) / 2;
                        bitmapSize.Height = pictureBox1.MinimumSize.Height;
                        translate = true;
                    }

                    if (translate)
                    {
                        Bitmap modified = new Bitmap(bitmapSize.Width, bitmapSize.Height);
                        using (Graphics gfx = Graphics.FromImage(modified))
                        {
                            gfx.TranslateTransform(xTranslate, yTranslate);
                            gfx.DrawImage(capturedImage, 0, 0);
                        }
                        capturedImage.Dispose();
                        if (pictureBox1.Image != null)
                            pictureBox1.Image.Dispose();
                        pictureBox1.Image = modified;
                    }
                    else
                    {
                        if (pictureBox1.Image != null)
                            pictureBox1.Image.Dispose();
                        pictureBox1.Image = capturedImage;
                    }
                    this.Opacity = 1.0;
                    this.BringToFront();
                    captured = true;
                }
            }
            base.WndProc(ref m);
        }

        /// <summary>
        /// Se clicca il pulsante window allora catturo una finestra
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            this.windowMode = true;
            this.Opacity = 0.0;
            Hook(Handle);
        }

        /// <summary>
        /// Se clicca il pulsante Screen part allora catturo una parte dello schermo
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            this.windowMode = false;
            ScreenFrame frameChooser = new ScreenFrame();

            this.Opacity = 0.0;
            DialogResult ris = frameChooser.ShowDialog();

            if (ris == DialogResult.OK)
            {
                bool translate = false;

                float xTranslate = 0.0F;
                float yTranslate = 0.0F;

                screenSize = frameChooser.CaptureSize;
                screenStartPoint = frameChooser.CaptureStart;

                Bitmap capturedImage = CaptureClass.CaptureScreen(CapturedRectangle);

                Size bitmapSize = capturedImage.Size;

                if (bitmapSize.Width < pictureBox1.MinimumSize.Width)
                {
                    xTranslate = (pictureBox1.MinimumSize.Width - bitmapSize.Width) / 2;
                    bitmapSize.Width = pictureBox1.MinimumSize.Width;
                    translate = true;
                }
                if (bitmapSize.Height < pictureBox1.MinimumSize.Height)
                {
                    yTranslate = (pictureBox1.MinimumSize.Height - bitmapSize.Height) / 2;
                    bitmapSize.Height = pictureBox1.MinimumSize.Height;
                    translate = true;
                }

                if (translate)
                {
                    Bitmap modified = new Bitmap(bitmapSize.Width, bitmapSize.Height);
                    using (Graphics gfx = Graphics.FromImage(modified))
                    {
                        gfx.TranslateTransform(xTranslate, yTranslate);
                        gfx.DrawImage(capturedImage, 0, 0);
                    }
                    capturedImage.Dispose();
                    if (pictureBox1.Image != null)
                        pictureBox1.Image.Dispose();
                    pictureBox1.Image = modified;
                }
                else
                {
                    if (pictureBox1.Image != null)
                        pictureBox1.Image.Dispose();
                    pictureBox1.Image = capturedImage;
                }
                this.Opacity = 1;
                captured = true;
            }
            else 
            {
                this.Opacity = 1;
                captured = false;
            }
            frameChooser.Dispose();
        }

        private void pictureBox1_Resize(object sender, EventArgs e)
        {
            this.ClientSize = new Size(pictureBox1.Width + 2 * pictureBox1.Location.X, pictureBox1.Height + pictureBox1.Location.Y + 79);
        }

        private void ScreenChooser_Resize(object sender, EventArgs e)
        {
            int newWindowButtonX = this.ClientSize.Width / 2 - (WindowButton.Width + 6 + ScreenButton.Width) / 2;
            WindowButton.Left = newWindowButtonX;
            ScreenButton.Left = WindowButton.Left + WindowButton.Width + 6;

            Point newCancelLocation = new Point(this.ClientSize.Width - 12 - OKButton.Width - 6 - CancButton.Width,
                                                this.ClientSize.Height - 12 - CancButton.Height);
            OKButton.Location = newCancelLocation;
            newCancelLocation.X += (CancButton.Width + 6);
            CancButton.Location = newCancelLocation;
        }

        private void OKButton_Click(object sender, EventArgs e)
        {
            if (captured)
            {
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }
    }
}
